-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add visibility option to dashboard cards #20840
Conversation
d6f69f6
to
1a76eec
Compare
6468ff2
to
12069a1
Compare
const mediaQueries = extractMediaQueries(conditions); | ||
|
||
const listeners = mediaQueries.map((query) => { | ||
const listener = listenMediaQuery(query, () => { | ||
const visibility = checkConditionsMet(conditions, hass); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved checkConditionsMet
outside of this function because hass
value wasn't updated.
Warning Rate Limit Exceeded@piitaya has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 23 minutes and 52 seconds before requesting another review. How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. WalkthroughThe changes primarily focus on refactoring and consolidating the type usage for Changes
Sequence Diagram(s) (Beta)sequenceDiagram
participant User
participant LovelaceView
participant HuiCard
participant MediaQuery
User->>LovelaceView: Load View
LovelaceView->>HuiCard: Create Card
HuiCard->>MediaQuery: Listen for Conditions
MediaQuery->>HuiCard: Update Visibility
HuiCard->>LovelaceView: Render Card
LovelaceView->>User: Display View
sequenceDiagram
participant User
participant CardEditor
participant LovelaceCardConfig
participant Condition
User->>CardEditor: Open Card Editor
CardEditor->>LovelaceCardConfig: Add/Edit Card
LovelaceCardConfig->>Condition: Set Visibility Conditions
Condition->>LovelaceCardConfig: Apply Conditions
LovelaceCardConfig->>CardEditor: Save Config
CardEditor->>User: Confirm Changes
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (invoked as PR comments)
Additionally, you can add CodeRabbit Configration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
Outside diff range comments (19)
src/data/lovelace.ts (1)
Line range hint
1-12
: Optimize imports to use type-only imports where appropriate.- import { Connection, getCollection, HassEventBase } from "home-assistant-js-websocket"; - import { HuiCard } from "../panels/lovelace/cards/hui-card"; - import { HuiSection } from "../panels/lovelace/sections/hui-section"; - import { Lovelace, LovelaceBadge } from "../panels/lovelace/types"; - import { HomeAssistant } from "../types"; - import { LovelaceSectionConfig } from "./lovelace/config/section"; - import { fetchConfig, LegacyLovelaceConfig } from "./lovelace/config/types"; - import { LovelaceViewConfig } from "./lovelace/config/view"; + import type { Connection, getCollection, HassEventBase } from "home-assistant-js-websocket"; + import type { HuiCard } from "../panels/lovelace/cards/hui-card"; + import type { HuiSection } from "../panels/lovelace/sections/hui-section"; + import type { Lovelace, LovelaceBadge } from "../panels/lovelace/types"; + import type { HomeAssistant } from "../types"; + import type { LovelaceSectionConfig } from "./lovelace/config/section"; + import type { fetchConfig, LegacyLovelaceConfig } from "./lovelace/config/types"; + import type { LovelaceViewConfig } from "./lovelace/config/view";src/panels/lovelace/components/hui-conditional-base.ts (1)
Line range hint
124-145
: Avoid using non-null assertions. Consider checking for null or undefined before usage.- this._config!.conditions, - this.hass! + this._config?.conditions, + this.hasssrc/panels/lovelace/views/hui-panel-view.ts (1)
Line range hint
70-119
: Avoid using non-null assertions. Consider checking for null or undefined before usage.- this.hass!.localize( + this.hass?.localize(src/panels/lovelace/views/hui-sidebar-view.ts (2)
Line range hint
46-46
: Avoid using non-null assertions as they bypass TypeScript's strict null checks.- this._mql?.removeListener(this._mqlListenerRef!); + if (this._mqlListenerRef) { + this._mql?.removeListener(this._mqlListenerRef); + }Also applies to: 94-94, 126-126, 137-137, 153-153, 164-164, 165-165, 166-166
Line range hint
1-9
: Optimize imports by usingimport type
for type-only imports to reduce runtime overhead and improve build performance.- import { mdiArrowLeft, mdiArrowRight, mdiPlus } from "@mdi/js"; - import { - CSSResultGroup, - LitElement, - PropertyValues, - TemplateResult, - css, - html, - } from "lit"; - import { property, state } from "lit/decorators"; + import type { mdiArrowLeft, mdiArrowRight, mdiPlus } from "@mdi/js"; + import type { + CSSResultGroup, + LitElement, + PropertyValues, + TemplateResult, + css, + html, + } from "lit"; + import type { property, state } from "lit/decorators";Also applies to: 14-15, 15-16
src/panels/lovelace/sections/hui-grid-section.ts (2)
Line range hint
53-53
: Avoid using non-null assertions as they bypass TypeScript's strict null checks.- const card = this.cards![idx]; + if (this.cards) { + const card = this.cards[idx]; + // Further logic involving `card` + }Also applies to: 95-95, 149-149, 153-153
Line range hint
1-2
: Optimize imports by usingimport type
for type-only imports to reduce runtime overhead and improve build performance.- import { mdiPlus } from "@mdi/js"; - import { CSSResultGroup, LitElement, css, html, nothing } from "lit"; + import type { mdiPlus } from "@mdi/js"; + import type { CSSResultGroup, LitElement, css, html, nothing } from "lit";Also applies to: 8-9, 9-10, 16-17
src/panels/lovelace/editor/card-editor/hui-dialog-suggest-card.ts (2)
Line range hint
66-66
: Avoid using non-null assertions as they bypass TypeScript's strict null checks.- this._yamlEditor.setValue(this._cardConfig); + if (this._yamlEditor && this._cardConfig) { + this._yamlEditor.setValue(this._cardConfig); + }Also applies to: 108-108, 131-131, 132-132, 139-139, 158-158, 219-219, 220-220, 221-221, 222-222, 232-232, 249-249, 268-268
Line range hint
1-2
: Optimize imports by usingimport type
for type-only imports to reduce runtime overhead and improve build performance.- import deepFreeze from "deep-freeze"; - import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; + import type { deepFreeze } from "deep-freeze"; + import type { css, CSSResultGroup, html, LitElement, nothing } from "lit";Also applies to: 7-8, 8-9, 9-10, 12-13, 16-20, 22-23
src/panels/lovelace/common/validate-condition.ts (3)
Line range hint
209-216
: Prefer usingfor...of
for iterating over arrays for better readability and performance.- [].forEach((state) => { + for (const state of []) {
Line range hint
123-123
: ReplaceisNaN
withNumber.isNaN
for safer checks without type coercion.- if (isNaN(numericState)) { + if (Number.isNaN(numericState)) {Also applies to: 129-129, 132-132
Line range hint
1-5
: Optimize imports by usingimport type
for type-only imports to reduce runtime overhead and improve build performance.- import { ensureArray } from "../../../common/array/ensure-array"; - import { - MediaQueriesListener, - listenMediaQuery, - } from "../../../common/dom/media_query"; + import type { ensureArray } from "../../../common/array/ensure-array"; + import type { + MediaQueriesListener, + listenMediaQuery, + } from "../../../common/dom/media_query";Also applies to: 7-8
src/panels/lovelace/sections/hui-section.ts (2)
Line range hint
60-60
: Avoid using non-null assertions as they bypass TypeScript's strict null checks.- this._cards = this._cards!.map((curCardEl) => + if (this._cards) { + this._cards = this._cards.map((curCardEl) =>Also applies to: 116-122, 119-119, 127-134, 131-131, 146-146, 177-177, 198-198, 199-199, 200-200, 201-201, 202-202, 203-203, 259-259, 259-259, 261-261, 285-285, 287-287
Line range hint
1-1
: Optimize imports by usingimport type
for type-only imports to reduce runtime overhead and improve build performance.- import { PropertyValues, ReactiveElement } from "lit"; - import { customElement, property, state } from "lit/decorators"; + import type { PropertyValues, ReactiveElement } from "lit"; + import type { customElement, property, state } from "lit/decorators";Also applies to: 2-3
src/panels/lovelace/views/hui-masonry-view.ts (3)
Line range hint
70-72
: Consider replacingforEach
withfor...of
for better readability and performance in modern JavaScript.- this._mqls?.forEach((mql) => { - mql.removeListener(this._mqlListenerRef!); - }); + for (const mql of this._mqls || []) { + mql.removeListener(this._mqlListenerRef!); + }
Line range hint
71-71
: Avoid using non-null assertions. Consider adding checks or using optional chaining.- this._mqlListenerRef!(); + this._mqlListenerRef?.();Also applies to: 91-91, 119-119, 134-134, 153-153, 154-154, 165-165, 239-239, 246-246, 260-260, 276-276
Line range hint
172-172
: ReplaceforEach
withfor...of
for iterating over arrays.- columnElements.forEach((column) => { - if (!column.lastChild) { - column.parentElement!.removeChild(column); - } - }); + for (const column of columnElements) { + if (!column.lastChild) { + column.parentElement?.removeChild(column); + } + }Also applies to: 244-248
src/panels/lovelace/views/hui-view.ts (2)
Line range hint
87-87
: Avoid using non-null assertions. Consider adding checks or using optional chaining.- this.lovelace!.editMode + this.lovelace?.editModeAlso applies to: 125-125, 277-277, 299-299, 300-300, 301-301, 302-302, 303-303, 304-304
Line range hint
178-184
: ReplaceforEach
withfor...of
for iterating over arrays to improve readability and performance.- this._badges.forEach((badge) => { - try { - badge.hass = this.hass; - } catch (e: any) { - this._rebuildBadge(badge, createErrorBadgeConfig(e.message)); - } - }); + for (const badge of this._badges) { + try { + badge.hass = this.hass; + } catch (e: any) { + this._rebuildBadge(badge, createErrorBadgeConfig(e.message)); + } + }Also applies to: 186-192, 194-200, 221-228, 229-236
@@ -4,4 +4,5 @@ export const baseLovelaceCardConfig = object({ | |||
type: string(), | |||
view_layout: any(), | |||
layout_options: any(), | |||
visibility: any(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Specify a more appropriate type for visibility
.
- visibility: any(),
+ visibility: array(Condition),
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.
visibility: any(), | |
visibility: array(Condition), |
@@ -7,4 +8,5 @@ export interface LovelaceCardConfig { | |||
layout_options?: LovelaceLayoutOptions; | |||
type: string; | |||
[key: string]: any; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Specify a more appropriate type for view_layout
.
- view_layout?: any,
+ view_layout?: LovelaceLayoutOptions,
Committable suggestion was skipped due low confidence.
import { promiseTimeout } from "../../../common/util/promise-timeout"; | ||
import { HuiCard } from "../cards/hui-card"; | ||
import { LovelaceCard, LovelaceHeaderFooter } from "../types"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optimize imports to use type-only imports where appropriate.
- import { HuiCard } from "../cards/hui-card";
- import { LovelaceCard, LovelaceHeaderFooter } from "../types";
+ import type { HuiCard } from "../cards/hui-card";
+ import type { LovelaceCard, LovelaceHeaderFooter } from "../types";
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.
import { promiseTimeout } from "../../../common/util/promise-timeout"; | |
import { HuiCard } from "../cards/hui-card"; | |
import { LovelaceCard, LovelaceHeaderFooter } from "../types"; | |
import { promiseTimeout } from "../../../common/util/promise-timeout"; | |
import type { HuiCard } from "../cards/hui-card"; | |
import type { LovelaceCard, LovelaceHeaderFooter } from "../types"; |
} | ||
|
||
private _clearMediaQueries() { | ||
this._listeners.forEach((unsub) => unsub()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer using for...of
for iterating over arrays for better readability and performance.
- this._listeners.forEach((unsub) => unsub());
+ for (const unsub of this._listeners) {
+ unsub();
+ }
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.
this._listeners.forEach((unsub) => unsub()); | |
for (const unsub of this._listeners) { | |
unsub(); | |
} |
while (this.lastChild) { | ||
this.removeChild(this.lastChild); | ||
} | ||
this.appendChild(this._element!); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid using non-null assertions as they bypass TypeScript's strict null checks.
- this.appendChild(this._element!);
+ if (this._element) {
+ this.appendChild(this._element);
+ }
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.
this.appendChild(this._element!); | |
if (this._element) { | |
this.appendChild(this._element); | |
} |
@@ -0,0 +1,141 @@ | |||
import { PropertyValues, ReactiveElement } from "lit"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optimize imports by using import type
for type-only imports to reduce runtime overhead and improve build performance.
- import { PropertyValues, ReactiveElement } from "lit";
- import { customElement, property, state } from "lit/decorators";
- import { MediaQueriesListener } from "../../../common/dom/media_query";
+ import type { PropertyValues, ReactiveElement } from "lit";
+ import type { customElement, property, state } from "lit/decorators";
+ import type { MediaQueriesListener } from "../../../common/dom/media_query";
Also applies to: 2-3, 4-5
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.
import { PropertyValues, ReactiveElement } from "lit"; | |
import type { PropertyValues, ReactiveElement } from "lit"; | |
import type { customElement, property, state } from "lit/decorators"; | |
import type { MediaQueriesListener } from "../../../common/dom/media_query"; |
@@ -131,6 +124,14 @@ export class HuiSection extends ReactiveElement { | |||
} | |||
if (changedProperties.has("lovelace")) { | |||
this._layoutElement.lovelace = this.lovelace; | |||
this._cards.forEach((element) => { | |||
try { | |||
element.hass = this.hass; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to set hass again? We already did that on line 118?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so
@@ -131,6 +124,14 @@ export class HuiSection extends ReactiveElement { | |||
} | |||
if (changedProperties.has("lovelace")) { | |||
this._layoutElement.lovelace = this.lovelace; | |||
this._cards.forEach((element) => { | |||
try { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This try catch should probably be moved to hui-card
, same for the try catch when setting hass
on line 118.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will improve that in a next PR 👍
this._listeners = attachConditionMediaQueriesListeners( | ||
this._config.visibility, | ||
(matches) => { | ||
this._updateElement(hasOnlyMediaQuery && matches); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
const visible = visibility || this.lovelace!.editMode; | ||
this._updateElement(visible); | ||
(matches) => { | ||
this._updateElement(hasOnlyMediaQuery && matches); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's done in the updateElement but I agree, we should improve that.
return; | ||
} | ||
this._config = config; | ||
this._element = createCardElement(config); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hui-card
should probably also handle the rebuild logic, we can then remove it anywhere else.
- Rework procedure - add links to cards - related to home-assistant/frontend#20840
Proposed change
Attempt to add visibility to dashboard cards (Similar to #20805 for sections).
hui-card
componenthui-card
(To be improved).Type of change
Example configuration
Additional information
Checklist
If user exposed functionality or configuration variables are added/changed:
Summary by CodeRabbit
New Features
visibility
property for Lovelace cards, enhancing customization based on conditions.hasOnlyMediaQuery
to improve visibility logic in Lovelace components.Improvements
HuiCard
type, simplifying the configuration and rendering process.Bug Fixes
Refactor